package com.hezuti.common.url.dispatch;

import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import org.apache.log4j.Logger;

public class RequestDispatcher extends CommonDispatcher {
	protected final int CHECK_TIME_OUT = 1000;
	protected Timer checkTimer = null;
	protected Map checkMap = null;
	private static final Logger logger;
	
	static {
		logger = Logger.getLogger(RequestDispatcher.class);
	}
	
	class CheckTask extends TimerTask {
		public void run() {
			boolean reWeight = false;
			for(int i = 0; i < objectList.size(); i++) {
				IpObject obj = (IpObject) objectList.get(i);
				logger.debug("checking "+obj.getIp()+":"+obj.getPort()+" ...");
				try {
					Socket socket = new Socket();
					socket.connect(new InetSocketAddress(obj.getIp(), obj.getPort()), CHECK_TIME_OUT);
					socket.close();
					logger.debug(obj.getIp()+":"+obj.getPort()+" can connect");
					Integer weight = (Integer) checkMap.remove(obj);
					if(weight != null) {
						//resume initial weight
						obj.setWeight(weight);
						//need recalculate weight
						reWeight = true;
					}
				} catch (Exception ex) {
					logger.error(obj.getIp()+":"+obj.getPort()+" can't connect");
					if(!checkMap.containsKey(obj)) {
						//save initial weight
						checkMap.put(obj, new Integer(obj.getWeight()));
						//clear weight
						obj.setWeight(0);
						//need recalculate weight
						reWeight = true;
					}
				}
			}
			if(reWeight) {
				logger.info("recalculate weight");
				calculateWeight(objectList);
			}
		}
	}
	
	public void cancelTimer() {
		if(checkTimer != null) {
			logger.info("cancel timer");
			checkTimer.cancel();
		}
	}
	
	public RequestDispatcher(List<IpObject> list, int checkAlive) {
		
	    super(list);
		//checkAlive is set and remote host number larger than one
		if(checkAlive > 0 && list.size() > 1) {
			checkMap = new HashMap();
			checkTimer = new Timer();
			logger.info("schedule timer intevel "+checkAlive+" ms");
			CheckTask checkTask = new CheckTask();
			//check at start time, will delay tomcat start
			//checkTask.run();
			//random first time
			//checkTimer.schedule(checkTask, random.nextInt(checkAlive), checkAlive);
		}
	}
}